﻿using LightCAD.MathLib;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Metadata;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace LightCAD.MathLib
{
    public class Polygon2d : Curve2d
    {
        private bool? _isConvex;
        private Box2 _boundingBox;
        public Vector2[] Points { get; set; }

        public Polygon2d()
        {
            this.Type = Curve2dType.Polygon2d;
            this.IsClosed = true;
            this._boundingBox = null;
        }


        public override void Copy(Curve2d src)
        {
            var polygon = src as Polygon2d;
            this.Points = polygon.Points.Clone<Vector2>();
            this.Name = polygon.Name;
        }
        public override Curve2d Clone()
        {
            var newObj = new Polygon2d();
            newObj.Copy(this);
            return newObj;
        }

        public void Reset()
        {
            _boundingBox = null;
            _isConvex = null;
        }
        public Box2 BoundingBox
        {
            get
            {
                if (_boundingBox == null)
                {
                    _boundingBox = Box2.Empty;
                    _boundingBox = _boundingBox.ExpandByPoints(Points);
                }
                return _boundingBox;
            }
        }
      

        public void ApplyMatrix(Matrix3 matrix)
        {
            for (var i = 0; i < Points.Length; i++)
            {
                Points[i].ApplyMatrix3(matrix);
            }
        }
        public Polygon2d Multiply(Matrix3 matrix)
        {
            var newPoly = new Polygon2d { Points = new Vector2[this.Points.Length] };
            for (var i = 0; i < Points.Length; i++)
            {
                newPoly.Points[i] = matrix.MultiplyPoint(Points[i]);
            }
            return newPoly; 
        }
        public bool IsConvex
        {
            get
            {
                if(_isConvex == null)
                {
                    _isConvex = GeoUtils.IsConvexPolygon(this.Points);
                }
                return _isConvex.Value;
            }
        }


        public bool Contains(Vector2 point)
        {
            return GeoUtils.IsPointInPolygon(point, this.Points);
        }

        public override Curve2d Translate(Vector2 offset)
        {
            for (int i = 0; i < this.Points.Length; i++)
            {
                var p = this.Points[i];
                p.Add(offset);
            }
            this._boundingBox?.Max.Add(offset);
            this._boundingBox?.Min.Add(offset);
            return this;
        }

        public override Curve2d RotateAround(Vector2 basePoint, double angle)
        {
            for (int i = 0; i < this.Points.Length; i++)
            {
                var p = this.Points[i];
                p.RotateAround(basePoint,angle);
            }
            this._boundingBox = null;
            return this;
        }

        public override Curve2d Mirror(Vector2 axisStart, Vector2 axisDir)
        {
            for (int i = 0; i < this.Points.Length; i++)
            {
                var p = this.Points[i];
                p.Mirror(axisStart, axisDir);
            }
            this._boundingBox = null;
            return this;
        }
        public override Vector2[] GetPoints(int div = 5, double scaleInFuture = 1)
        {
            return this.Points.Select(p => p.Clone()).ToArray();
        }
    }
}
